/*
  * 	sys_handler.c: Handles the read(), and write() call
  *
  *	Date: Oct 26, 2008
  */
#include <exports.h>
#include <bits/swi.h>
#include <bits/fileno.h>
#include <bits/errno.h>
#include <sys_handler.h>

 /* ASCII Conversion */
#define BACKSPACE 8
#define EOT 4
#define DEL 127
#define NEW_LINE 10
#define CARRIAGE 13
  
  /* Macros for read handling */
#define SDRAM_START_ADDR	0xa0000000
#define SDRAM_END_ADDR		0xa3ffffff
#define SDRAM_MAX_SIZE		0x03ffffff	/* how many bytes are belonged to */

#define SDRAM_CHECKING(addr, len)			((len) <= SDRAM_MAX_SIZE &&(addr) >= SDRAM_START_ADDR &&(addr) <= (SDRAM_END_ADDR - (len)))

	/* Macros for write handling */
#define SFROM_START_ADDR	0x00000000
#define SFROM_END_ADDR		0x00ffffff
#define SFROM_MAX_SIZE		0x00ffffff

ssize_t read(int fd, void *buf, size_t count)
{
   unsigned int i = 0;
   char c;
   ssize_t ret;
   
   // checks whether the file descriptor matches stdin or not
   if (fd != STDIN_FILENO)
     return -EBADF;
   
   // checks whether the memory range specified by the buffer and
   // its max size exists outside the range of writable memory
   // SDRAM
   if (((unsigned int) buf + count) > 0xa3ffffff && (unsigned int) (buf) < 0xa0000000)
     return -EFAULT;
   
   while(tstc()==0);
   
   do 
     {
	c = getc();
	// EOT character handle
	if (c == 4) 
	  return ret = (ssize_t) i;
	// backspace or delete character handle
	else if (c == 8 || c == 127) 
	  {
	     // if the buffer is not empty
	     if (i != 0) 
		  i--;
	     else 
	       {
		  *((char *)((unsigned int)buf + i)) = c;   // read into buffer
		  puts("\b \b"); 
	       }
	  }
	else if (c==10 || c==13) 
	  {
	     putc(10);
	     *((char *) ((unsigned int)buf+i)) =10;
	     i++;
	     return ret = (ssize_t) i;
	  }
	else
	  {
	     *((char *)((unsigned int)buf + i)) = c;
	     putc(c);
	     i++;
	  }
     } while(i < sizeof(buf) || i != count);
   
   return ret = (ssize_t) i;
}

ssize_t write(int fd, const void *buf, size_t count){

   const char *block;
   size_t counter;
   
   block = (const char*)buf;
   counter=0;
   
   /* File descrpitor Checking */
   if (fd != STDOUT_FILENO){
      return -EBADF;
   }
   
   /* Memory Checking */
   if(!((((unsigned int)((unsigned int)buf+count-1)<=SFROM_END_ADDR)/*&&((unsigned int)buf>=SFROM_START_ADDR)*/)||(((unsigned int)((int)buf+count-1)<=SDRAM_END_ADDR)/*&&((unsigned int)buf>=SDRAM_START_ADDR)*/)))
     {
	return -EFAULT;
     }
   
   
   while(counter<count){
      putc(block[counter]);
      counter++;
   }
   
   return counter;
}  

//time returns the time in milliseconds that have elapsed since the 
//kernel booted up. This can be interpreted as the number of milliseconds 
//to ellapse since the kernel timer was turned on.
unsigned long time(void)
{
	// TODO: Implement this!	
	return (ticks * 10);

}

//sleep suspends the execution of the current task for the given time. 
//The task may continue executing after atleast the given time has elapsed.
void sleep(unsigned long millis)
{
	// TODO: Implement this!	
	unsigned int start = ticks*10; //time at the beginning of sleep
	while (((ticks * 10) - start) < millis); 
}


